/**
 * 文件描述如下：
 * 1. 初始化 场景 相机 渲染器
 * 2. 方便在Webgl.vue中调用
 * 3.
 * 4.
 */

// import { PerspectiveCamera, Scene, WebGLRenderer, AxesHelper, AmbientLight } from 'three'
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { Line2 } from 'three/addons/lines/Line2.js'
import { LineMaterial } from 'three/addons/lines/LineMaterial.js'
import { LineGeometry } from 'three/addons/lines/LineGeometry.js'
import { disposeObject } from '/src/utils/dispose.js'
// CSS2D
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js'
import Stats from 'three/addons/libs/stats.module.js'
import { mainStore } from '@/store/mainStore'
const store = mainStore()
import { addBmp } from './addBmp.js'

var colorMap = {
  0: 0xff0000,
  1: 0x00ff00,
  2: 0xffff00,
}
export default class ThreeApp {
  constructor() {
    this.offsetX = 6100 - (6100 + 6100 / 2)
    this.offsetY = 4950 - (4950 + 4950 / 2)
    // 初始化 场景 相机 渲染器
    this.container = document.querySelector('#webgl-eventDetection')
    this.WIDTH = this.container.clientWidth
    this.HEIGHT = this.container.clientHeight
    this.scene = new THREE.Scene()
    //
    this.camera = new THREE.PerspectiveCamera(50, this.WIDTH / this.HEIGHT, 0.1, 10000)
    this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })

    this.carGroupg = new THREE.Group() // 车辆组
    this.scene.add(this.carGroupg)
    this.LightsGroupg = new THREE.Group() // 信号灯与区域组
    this.scene.add(this.LightsGroupg)
    this.label2DGroup = new THREE.Group() // css2d的标签组
    this.scene.add(this.label2DGroup)

    this.render2D = new CSS2DRenderer() // 实例化css2d的渲染器
  }

  // 初始化所有
  init = () => {
    this.initCamera()
    this.initScene()
    this.initRenderer()
    this.initControls()
    // this.initStats()
    this.initCSS2DRenderer() // css2d的渲染器
  }

  // 初始化相机
  initCamera = () => {
    this.camera.position.set(0, 0, 3000)
  }

  // 初始化场景
  initScene = () => {
    // 创建坐标轴辅助器
    const axesHelper = new THREE.AxesHelper(500) // 5 是坐标轴的长度
    axesHelper.position.set(this.offsetX, -this.offsetY, 0)
    this.scene.add(axesHelper)
    // 创建环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 1) // 白色光，强度为 0.5
    // 将环境光添加到场景中
    this.scene.add(ambientLight)

    addBmp(this.scene) // 添加bmp图片
  }

  // 初始化渲染器
  initRenderer = () => {
    this.renderer = new THREE.WebGLRenderer()
    this.renderer.setPixelRatio(window.devicePixelRatio)
    this.renderer.setSize(this.WIDTH, this.HEIGHT)
    this.renderer.setAnimationLoop(this.render)
    this.renderer.setClearColor(0x000000, 1) // 0 表示完全透明
    this.container.appendChild(this.renderer.domElement)
    window.addEventListener('resize', () => window.location.reload())
  }

  // 初始化控制器
  initControls = () => {
    this.controls = new OrbitControls(this.camera, this.renderer.domElement)
    // this.controls.enableDamping = true
    this.controls.enableRotate = false // 禁用旋转
    this.controls.screenSpacePanning = true // 启用屏幕空间平移
    this.controls.maxDistance = 5000
    this.controls.minDistance = 100
  }

  // 初始化 帧率 内存 等信息
  initStats = () => {
    this.stats = new Stats()
    this.container.appendChild(this.stats.dom)
  }

  // 动画函数
  render = () => {
    this.renderer.render(this.scene, this.camera)
    if (this.stats) this.stats.update()
    this.controls.update()
    // 标签渲染器渲染
    this.render2D.render(this.scene, this.camera)
  }
  initCSS2DRenderer() {
    this.render2D.setSize(this.WIDTH, this.HEIGHT)
    this.container.appendChild(this.render2D.domElement)
    //设置样式
    this.render2D.domElement.style.position = 'absolute'
    this.render2D.domElement.style.top = '25px'
    this.render2D.domElement.style.left = '0px'
    this.render2D.domElement.style.pointerEvents = 'none'
  }
  // 2D的dom标签
  css2dLabel(targePosition, targetId, centerX, centerY) {
    let div = document.getElementById(targetId)
    if (!div) {
      return false
    }
    var label = new CSS2DObject(div)
    label.position.set(targePosition.x, targePosition.y, targePosition.z)
    label.center = new THREE.Vector2(centerX, centerY)
    label.name = targetId
    this.label2DGroup.add(label)
  }
  update2dLabel(targePosition, targetId, isShow) {
    let label = this.label2DGroup.getObjectByName(targetId)
    label.visible = isShow
    if (targePosition) {
      label.position.set(targePosition.x, targePosition.y, targePosition.z)
    }
  }
  // 渲染车辆
  renderGeometry = (array) => {
    this.carGroupg.children = []
    const foundItem = array?.find((target) => {
      return target.webDetectInfo.id === store.activeCar
    })
    if (foundItem) {
      let webDetectInfo = foundItem.webDetectInfo
      // console.log('ID 存在于数组中',webDetectInfo);
      let obj = {
        centerPx: this.offsetX + webDetectInfo.centerPx,
        centerPy: -(this.offsetY + webDetectInfo.centerPy),
      }
      store.update_active_carInfo(Object.assign({}, webDetectInfo, obj))
    } else {
      store.update_active_carInfo(null)
    }
    array?.map((target) => {
      // 定义四个点来表示四边形的顶点
      let item = target.webDetectInfo
      const vertices = [new THREE.Vector3(this.offsetX + item.frontLeftPx, -(this.offsetY + item.frontLeftPy), 0), new THREE.Vector3(this.offsetX + item.behindLeftPx, -(this.offsetY + item.behindLeftPy), 0), new THREE.Vector3(this.offsetX + item.behindRightPx, -(this.offsetY + item.behindRightPy), 0), new THREE.Vector3(this.offsetX + item.frontRightPx, -(this.offsetY + item.frontRightPy), 0)]
      // console.log(vertices)
      // 创建 BufferGeometry
      const geometry = new THREE.BufferGeometry().setFromPoints(vertices)
      // 添加面索引以形成两个三角形
      const indices = [
        0,
        1,
        2, // 第一个三角形
        0,
        2,
        3, // 第二个三角形
      ]
      geometry.setIndex(indices)
      // 创建材质
      const material = new THREE.MeshBasicMaterial({ color: item.eventType == -1 ? this.filterColor(item) : 0xff0000, side: THREE.DoubleSide })
      // 创建网格
      const mesh = new THREE.Mesh(geometry, material)
      mesh.name = item.id
      this.carGroupg.add(mesh)
    })
  }
  filterColor = (obj) => {
    let color = 0xcccccc
    if (obj.statisticsFlag != -1) {
      color = 0x00ced1
    } else if (obj.centerFlag != -1) {
      color = 0xe6a23c
    } else if (obj.sidewalkFlag != -1) {
      color = 0x67c23a
    } else if (obj.peresTrainWaitingFlag != -1) {
      color = 0x409eff
    }
    return color
  }
  // 渲染区域及红绿灯
  renderAreaAndLights = (array) => {
    this.LightsGroupg.children = []
    array.map((item) => {
      // 车道号 item.laneOrSidewalkNo
      let lightColor = colorMap[item.webLightInfo.lightStatus]
      if (lightColor) {
        // 大于1属于区域，1是红绿灯
        if (item.webLightInfo?.pixes?.length > 1) {
          // 创建四边形的顶点
          const vertices = item.webLightInfo.pixes.map((element) => {
            return new THREE.Vector3(this.offsetX + element.x, -(this.offsetY + element.y), 0)
          })
          // 创建几何体
          const geometry = new LineGeometry()
          geometry.setPositions(vertices.flatMap((v) => [v.x, v.y, v.z]))
          const material = new LineMaterial({
            color: lightColor,
            linewidth: 5, // 设置线条宽度
            resolution: new THREE.Vector2(window.innerWidth, window.innerHeight), // 分辨率
            dashed: false,
          })
          // 创建线条
          const line = new Line2(geometry, material)
          // 将线条添加到场景中
          this.LightsGroupg.add(line)
        } else {
          let xy = item?.webLightInfo?.pixes?.[0] ?? 0 // 小周修改 原来没有三元表达式
          // 创建圆形几何体
          const geometry = new THREE.CircleGeometry(10, 32) // 半径为10，分段数为32
          // 创建红色材质
          const material = new THREE.MeshBasicMaterial({ color: lightColor, side: THREE.DoubleSide })
          // 创建网格对象#FFFF00
          const circle = new THREE.Mesh(geometry, material)
          circle.position.set(this.offsetX + xy.x, -(this.offsetY + xy.y), 0)
          // 将圆形添加到场景中
          this.LightsGroupg.add(circle)
        }
      }
    })
  }
  // 获取相交几何体
  meshOnClick = (event) => {
    event.preventDefault()
    const pointer = new THREE.Vector2()
    let raycaster = new THREE.Raycaster()
    pointer.x = (event.offsetX / this.WIDTH) * 2 - 1
    pointer.y = -(event.offsetY / this.HEIGHT) * 2 + 1
    raycaster.setFromCamera(pointer, this.camera)
    //geometrys为需要监听的Mesh合集，可以通过这个集合来过滤掉不需要监听的元素例如地面天空
    //true为不拾取子对象
    let intersects = raycaster.intersectObjects(this.carGroupg.children, true)
    //被射线穿过的几何体为一个集合，越排在前面说明其位置离端点越近，所以直接取[0]
    if (intersects.length > 0) {
      let id = intersects[0].object.name
      store.update_active_car(store.activeCar == id ? null : id)
      // console.warn(id, store.activeCar)
    } else {
      //若没有几何体被监听到，可以做一些取消操作
    }
    // return intersects
  }
  /**
   * 当渲染尺寸发生变化时触发
   *
   */
  resize = (WIDTH, HEIGHT) => {
    this.camera.aspect = WIDTH / HEIGHT
    this.camera.updateProjectionMatrix()
    this.renderer.setSize(WIDTH, HEIGHT)
    this.WIDTH = this.container.clientWidth
    this.HEIGHT = this.container.clientHeight
    this.renderer.setPixelRatio(window.devicePixelRatio)
  }

  destroyed() {
    // 销毁函数触发了
    disposeObject(this.scene)
  }
}
